package com.tbit.uqbike.service.business.impl;

import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.AccountUser;
import com.tbit.uqbike.object.pojo.StudentAuthApply;
import com.tbit.uqbike.object.pojo.User;
import com.tbit.uqbike.object.pojo.Usermsg;
import com.tbit.uqbike.object.pojo.dto.StudentAuthApplyDTO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.business.StudentAuthApplyService;
import com.tbit.uqbike.service.business.UserService;
import com.tbit.uqbike.webmanager.dao.core.AccountUserDao;
import com.tbit.uqbike.webmanager.dao.core.StudentAuthApplyDao;
import com.tbit.uqbike.webmanager.dao.core.UsermsgDao;
import com.tbit.uqbike.webmanager.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenmengran
 * @Description: 学生认证
 * @date 2020\1\6 000610:22
 */
@Slf4j
@Service
public class StudentAuthApplyServiceImpl implements StudentAuthApplyService {
    @Autowired
    private StudentAuthApplyDao studentAuthApplyDao;
    @Autowired
    private UserService userService;

    @Autowired
    private UsermsgDao usermsgDao;
    @Autowired
    private AccountUserDao accountUserDao;

    @Override
    public List<StudentAuthApply> queryPage(Integer accountId, Integer checkState, Date startDate, Date endDate) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("checkState", checkState);
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        return studentAuthApplyDao.getByAccountId(params);
    }


    @Override
    public Integer getTotal(Integer accountId, Integer checkState, String name, String studentNO,String phone,String startDate,
                            String endDate) {
        Map<String, Object> searchDate = new HashMap<>();
        try {
            //按时间筛选
            searchDate = this.getSearchDate(startDate, endDate);
        }catch (BaseException e){
            log.info("获取查询时间异常：{}",e.getMessage());
            return 0;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("checkState", checkState);
        params.put("name", name);
        params.put("studentNO", studentNO);
        params.put("phone",phone);
        params.putAll(searchDate);

        return studentAuthApplyDao.getTotal(params);
    }

    @Override
    public void edit(LoginInfo loginInfo, Integer applyId, String checkOpinion, Integer agree, String studentIdNo) {

        //权限验证
        StudentAuthApply studentAuthApply = studentAuthApplyDao.getById(applyId);
        /*if (!loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            if (studentAuthApply != null && !studentAuthApply.getAccountId().equals(loginInfo.id)) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }*/

        //todo 与白名单认证存在竞争 ,对 accountId 和 studentNO 进行加锁
        if (agree == 1) {
            /**审核通过，更新学生认证信息*/
            User user = userService.getByUserId(studentAuthApply.getUserId());
            if (user != null) {
                userService.updateStudentAuth(user.getUserId(), 1, studentIdNo);
                usermsgDao.insert(new Usermsg(user.getUserId(), "身份认证审核通知", "您身份认证已通过。"));
            }
        }

        //更新审核意见表
        Map<String, Object> params = new HashMap<>();
        params.put("applyId", applyId);
        params.put("checkState", agree);//审核状态
        params.put("checkOpinion", checkOpinion);
        params.put("checkTime", new Date());
        params.put("checkUserId", loginInfo.getAccountUserId());
        studentAuthApplyDao.updateApply(params);
    }

    public void clearAuthInfo(Integer userId){
        userService.clearStudentAuth(userId);
        studentAuthApplyDao.deleteByUserId(userId);

    }

    @Override
    public Result<StudentAuthApply> getStudentApplyById(Integer userId) {
        StudentAuthApply studentAuthApply = studentAuthApplyDao.getStudentApplyById(userId);
        return Result.success(studentAuthApply);
    }

    /**
     * 学生认证分页
     *
     * @param accountId
     * @param checkState
     * @param name
     * @param studentNO
     * @param sortName
     * @param rowCount
     * @param pageNO
     * @return
     */
    @Override
    public List<StudentAuthApplyDTO> queryPageV2(Integer accountId, Integer checkState, String name,
                                                 String studentNO,String phone, String sortName, Integer rowCount, Integer pageNO,
                                                 String startDate, String endDate) {
        Map<String, Object> searchDate = new HashMap<>();
        try {
            //按时间筛选
            searchDate = this.getSearchDate(startDate, endDate);
        }catch (BaseException e){
            log.info("获取查询时间异常：{}",e.getMessage());
            return null;
        }

        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("checkState", checkState);
        params.put("name", name);
        params.put("studentNO", studentNO);
        params.put("sortName", sortName);
        params.put("start", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);
        params.put("phone",phone);
        params.putAll(searchDate);
        return studentAuthApplyDao.queryPageV2(params);
    }

    /**
     * @description: 封装审核批人名和用户手机号码
     * @author: mo.shanyong
     * @date: 2024/11/27 16:00
     * @param: studentAuthApplies
     * @return: java.util.List<com.tbit.uqbike.object.pojo.dto.StudentAuthApplyDTO>
     */
    public List<StudentAuthApplyDTO> getStudentAuthApplyDTOs(List<StudentAuthApply> studentAuthApplies){
        List<StudentAuthApplyDTO> studentAuthApplyDTOS = new ArrayList<>();
        for (StudentAuthApply studentAuthApply : studentAuthApplies) {
            StudentAuthApplyDTO studentAuthApplyDTO = new StudentAuthApplyDTO();
            BeanUtils.copyProperties(studentAuthApply,studentAuthApplyDTO);
            studentAuthApplyDTOS.add(studentAuthApplyDTO);
        }
        //审批人名
        Map<Integer, String> checkUserNameMap = new HashMap<>();
        //审核人Id
        List<Integer> checkUserIdList = studentAuthApplies.stream().filter(studentAuthApply -> {
            return Objects.nonNull(studentAuthApply.getCheckUserId());
        }).map(StudentAuthApply::getCheckUserId).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(checkUserIdList)){
            List<AccountUser> accountUserList = accountUserDao.getAccountUserByIds(checkUserIdList);
            if (CollectionUtils.isNotEmpty(accountUserList)){
                checkUserNameMap = accountUserList.stream().collect(Collectors.toMap(AccountUser::getAccountUserId,AccountUser::getName));
            }
        }
        //用户Id
        List<Integer> userIdList = studentAuthApplies.stream().map(StudentAuthApply::getUserId).distinct().collect(Collectors.toList());
        List<User> userList = userService.getByUserIdBatch(userIdList);
        //用户手机号码
        Map<Integer, String> userPhoneMap = userList.stream().collect(Collectors.toMap(User::getUserId,User::getPhone));
        Map<Integer, String> finalCheckUserNameMap = checkUserNameMap;
        studentAuthApplyDTOS.forEach(studentAuthApplyDTO -> {
            studentAuthApplyDTO.setCheckUserName(finalCheckUserNameMap.get(studentAuthApplyDTO.getCheckUserId()));
            studentAuthApplyDTO.setUserPhone(userPhoneMap.get(studentAuthApplyDTO.getUserId()));
        });
        return studentAuthApplyDTOS;
    }

    /**
     * @description: 获取查询的时间区间
     * @author: mo.shanyong
     * @date: 2024/11/28 10:23
     * @param: startDate
     * @param: endDate
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    public Map<String,Object> getSearchDate(String startDate, String endDate){
        Map<String, Object> dateMap = new HashMap<>();
        LocalDate now = LocalDate.now();
        LocalDateTime nowTime = LocalDateTime.now();
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter zeroTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //没设置查询时间段，查最近一个月的
        if (StringUtils.isBlank(startDate) && StringUtils.isBlank(endDate)){
            // 获取本月的第一天
            LocalDate firstDayOfMonth = now.withDayOfMonth(1);
            // 将日期转换为日期时间，时间设置为0点0分0秒
            LocalDateTime startOfDay = firstDayOfMonth.atStartOfDay();
            startDate = startOfDay.format(zeroTimeFormatter);
            endDate = nowTime.format(timeFormatter);
            dateMap.put("startDate",startDate);
            dateMap.put("endDate",endDate);
            return dateMap;

        }
        //最多允许查询最近6个月
        LocalDateTime sixMonthsAgo = nowTime.minusMonths(6);
        if(StringUtils.isNotBlank(startDate)){
            try {
                long startTime = dateFormat.parse(startDate).getTime();
                String sixMonthTimeStr = sixMonthsAgo.format(zeroTimeFormatter);
                long sixMonthTime = dateFormat.parse(sixMonthTimeStr).getTime();
                if (startTime < sixMonthTime){
                    startDate = sixMonthTimeStr;
                }
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        }
        if (StringUtils.isNotBlank(endDate)){
            try {
                long endTime = dateFormat.parse(endDate).getTime();
                String sixMonthTimeStr = sixMonthsAgo.format(zeroTimeFormatter);
                long sixMonthTime = dateFormat.parse(sixMonthTimeStr).getTime();
                if (endTime < sixMonthTime){
                    throw new BaseException("筛选最大时间小于允许查询的最小时间");
                }
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }

        }
        dateMap.put("startDate",startDate);
        dateMap.put("endDate",endDate);
        return dateMap;
    }
}
